package myJs

import myJs.Implicits._
import myJs.myPkg.jquery._
import myJs.myPkg._
import myJs.myPkg.d3.d3T
import myJs.tool.Pojo.FilterContentData
import myJs.tool.Tool
import org.scalajs.dom.ext.Ajax
import org.scalajs.dom.{Element, Node, document}
import scalatags.Text.all._

import scala.collection.immutable.SeqMap
import scala.concurrent.ExecutionContext.Implicits.global
import scala.scalajs.js
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.JSConverters._
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import scala.scalajs.js.Dynamic.{global => g}
import scala.scalajs.js.JSON

/**
 * Created by yz on 11/5/2020
 */
@JSExportTopLevel("PhyTree")
object PhyTree {

  var tree: Phylotree = _

  @JSExport("init")
  def init = {
    refreshTree
    registerEvent
  }

  def refreshTree = {
    val index = layer.load(1, Tool.layerOptions.copy(shade=List("0.1", "#fff")))
    val url = g.jsRoutes.controllers.TreeController.getNwk().url.toString
    Ajax.get(url = s"${url.noCache}", headers = Map("Content-Type" -> "application/json")).map { xhr =>
      val rs = xhr.responseText.toJDS
      val containerId = "tree_container"
      val d3 = g.d3.asInstanceOf[d3T]
      val element = d3.select(s"#${containerId}")
      val width = $(s"#${containerId}").width()
      val height = $(s"#${containerId}").height()
      val nwk = rs("str")
      //      val nwk = "(((EELA:0.150276,CONGERA:0.213019):0.230956,(EELB:0.263487,CONGERB:0.202633):0.246917):0.094785,((CAVEFISH:0.451027,(GOLDFISH:0.340495,ZEBRAFISH:0.390163):0.220565):0.067778,((((((NSAM:0.008113,NARG:0.014065):0.052991,SPUN:0.061003,(SMIC:0.027806,SDIA:0.015298,SXAN:0.046873):0.046977):0.009822,(NAUR:0.081298,(SSPI:0.023876,STIE:0.013652):0.058179):0.091775):0.073346,(MVIO:0.012271,MBER:0.039798):0.178835):0.147992,((BFNKILLIFISH:0.317455,(ONIL:0.029217,XCAU:0.084388):0.201166):0.055908,THORNYHEAD:0.252481):0.061905):0.157214,LAMPFISH:0.717196,((SCABBARDA:0.189684,SCABBARDB:0.362015):0.282263,((VIPERFISH:0.318217,BLACKDRAGON:0.109912):0.123642,LOOSEJAW:0.397100):0.287152):0.140663):0.206729):0.222485,(COELACANTH:0.558103,((CLAWEDFROG:0.441842,SALAMANDER:0.299607):0.135307,((CHAMELEON:0.771665,((PIGEON:0.150909,CHICKEN:0.172733):0.082163,ZEBRAFINCH:0.099172):0.272338):0.014055,((BOVINE:0.167569,DOLPHIN:0.157450):0.104783,ELEPHANT:0.166557):0.367205):0.050892):0.114731):0.295021)myroot";

      val phylotreeOptions = PhylotreeOptions
      tree = Phylotree().svg(element).radial(false).spacing_x(10, true).
        spacing_y(18, true)
      tree = tree(nwk).layout()
      layer.close(index)
      println("=out=")
    }

  }

  def registerEvent = {

    $(document.body).on("click", s"[data-direction]", "", (y: Element) => {
      spacingChange(y)
    })
    $(document.body).on("click", s"#sort_ascending", "", (y: Element) => {
      sortNodes(true)
    })
    $(document.body).on("click", s"#sort_descending", "", (y: Element) => {
      sortNodes(false)
    })
    $(document.body).on("click", s"#sort_original", "", (y: Element) => {
      val index = layer.load(1, Tool.layerOptions.copy(shade=List("0.1", "#fff")))
      tree.resort_children((a: PhyTreeNode, b: PhyTreeNode) => {
        a.original_child_order - b.original_child_order
      })
      layer.close(index)
    })
    $(document.body).on("change", s".phylotree-layout-mode", "", (y: Element) => {
      val index = layer.load(1, Tool.layerOptions.copy(shade=List("0.1", "#fff")))
      if ($(y).isChecked) {
        if (tree.radial() != ($(y).myDataStr("mode") == "radial")) {
          tree.radial(!tree.radial()).placenodes().update()
        }
      }
      layer.close(index)
    })
    $(document.body).on("change", s".phylotree-align-toggler", "", (y: Element) => {
      val index = layer.load(1, Tool.layerOptions.copy(shade=List("0.1", "#fff")))
      if ($(y).isChecked) {
        if (tree.align_tips($(y).myDataStr("align") == "right").isDdefined) {
          tree.placenodes().update()
        }
      }
      layer.close(index)
    })
    $(document.body).on("submit", s".myForm", "", (y: Element) => {
      val html = $("svg:first").outerHTMLSome
      $("#svgHtml").`val`(html)
      true
    })
  }

  def sortNodes(asc: Boolean) = {
    val index = layer.load(1, Tool.layerOptions.copy(shade=List("0.1", "#fff")))
    tree.traverse_and_compute((n: PhyTreeNode) => {
      val maxCountDepth = if (n.children.isDdefined && n.children.size > 0) {
        n.children.map(_.count_depth).max
      } else 0
      n.count_depth = 1 + maxCountDepth
    })
    tree.resort_children((a: PhyTreeNode, b: PhyTreeNode) => {
      val diff = a.count_depth - b.count_depth
      if (asc) diff else -(diff)
    })
    layer.close(index)
  }

  def spacingChange(y: Element) = {
    val index = layer.load(1, Tool.layerOptions.copy(shade=List("0.1", "#fff")))
    val amount = $(y).myDataInt("amount")
    if ($(y).myDataStr("direction") == "vertical") {
      tree.spacing_x(tree.spacing_x() + amount).update()
    } else {
      tree.spacing_y(tree.spacing_y() + amount).update()
    }
    layer.close(index)
  }

}
